<?php

require('binaryTree.php');
$funcs = require("funcList.php");

// 初始化序列
$n = 20;
$all = [];
$seqs = [];
$nf = count($funcs);
for ($i = 0; $i < $nf; $i++) {
    $all[$i] = $i;
}
for ($i = 0; $i < $n; $i++) {
    $len = rand(1, $nf - 1);
    shuffle($all);
    $seqs[$i] = array_slice($all, $len);
    // 不需要查看最终的函数则使用注释部分
    // shuffle($funcs);
    // $seqs[$i] = array_slice($funcs, $len);
}

// 载入数据
$X = [1, 2, 3];
$Y = [1.8, 2.9, 5.33];
$m = count($X);

// 计算误差
$mse = [];
foreach ($seqs as $seq) {
    $sum = 0;
    $fs = [];
    foreach ($seq as $k) {
        $fs[] = $funcs[$k];
    }
    for ($i = 0; $i < $m; $i++) {
        $sum += pow(transfunc($fs, $X[$i]) - $Y[$i], 2);
        // $sum += pow(transfunc($seq, $X[$i]) - $Y[$i], 2);
    }
    $mse[] = $sum;
}

$sum = 0;
foreach ($mse as &$v) {
    if (is_nan($v) || is_infinite($v) || $v > 1E9) {
        $v = 1E9;
    }
    $sum += $v;
}

// 不考虑差异程度(因为代码太难写)
asort($mse);
$new = [];
$keys = array_keys($mse);
// 保留前10个
for ($i = 0; $i < 10; $i++) {
    $clone[] = $seqs[$keys[$i]];
}

// 杂交
for ($i = 5; $i < count($keys) / 2; $i++) {
    $a2 = exchange($seqs[$keys[$i * 2]], $seqs[$keys[$i * 2 + 1]]);
    $new = array_merge($new, $a2);
}
// 突变
$r = rand(0, count($new) - 1);
$index = rand(0, count($new[$r]) - 1);
$new[$r][$index] = array_rand($funcs);
// 2倍后代
$new = array_merge($clone, $new);
$new = array_merge($new, $new);
// 自然选择，淘汰一半

// 序列转函数数组
function seq2func($vec)
{
    $fs = [];
    foreach ($vec as $v) {
        $fs[] = $funcs[$v];
    }
    return $fs;
}

// 计算 mse, 返回排过序的方差
function computeMse($vecs)
{
    $mse = [];
    foreach ($vecs as $vec) {
        $fs = seq2func($vec);
        $mse[] = pow(transfunc($fs, $X[$i]) - $Y[$i], 2);

        // 处理超出运算范围的数
        foreach ($mse as &$v) {
            if (is_nan($v) || is_infinite($v) || $v > 1E9) {
                $v = 1E9;
            }
        }
    }
    asort($mes);
    return $mse;
}


    // 交换染色体
    function exchange(array $vec1, array $vec2)
    {
        $l1 = count($vec1);
        $l2 = count($vec2);
        $r1 = rand(1, $l1 -1);
        $r2 = rand(1, $l2 -1);
        $a11 = array_slice($vec1, 0, $r1);
        $a12 = array_slice($vec1, $r1);
        $a21 = array_slice($vec2, 0, $r2);
        $a22 = array_slice($vec2, $r2);
        return [
            array_merge($a11, $a22),
            array_merge($a21, $a12),
        ];
    }

        function selection($vecs)
        {

        }
